package com.fary.boot.autoconfigure.validation;

import com.fary.beans.factory.config.BeanDefinition;
import com.fary.beanvalidation.MethodValidationPostProcessor;
import com.fary.boot.autoconfigure.condition.ConditionalOnClass;
import com.fary.context.annotation.*;
import com.fary.core.env.Environment;
import com.fary.validation.Validator;

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(ExecutableValidator.class)
@ConditionalOnResource(resources = "classpath:META-INF/services/javax.validation.spi.ValidationProvider")
@Import(PrimaryDefaultValidatorPostProcessor.class)
public class ValidationAutoConfiguration {

	// 向容器注册一个 bean LocalValidatorFactoryBean defaultValidator,
	// 仅在容器中不存在类型为 Validator 的 bean时才注册该bean定义
	// 这是Spring 框架各部分缺省使用的 validator , 基于对象属性上的验证注解验证对象属性值
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	@ConditionalOnMissingBean(Validator.class)
	public static LocalValidatorFactoryBean defaultValidator() {
		LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
		MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory();
		factoryBean.setMessageInterpolator(interpolatorFactory.getObject());
		return factoryBean;
	}

	// 向容器注册一个 bean MethodValidationPostProcessor methodValidationPostProcessor
	// 这是一个 BeanPostProcessor, 它基于容器中存在的 bean Validator构建一个 MethodValidationInterceptor，
	// 这是一个方法调用拦截器，然后该 BeanPostProcessor 会为那些使用了注解 @Validated 的 bean
	// 创建代理对象，并使用所创建的 MethodValidationInterceptor 包裹该 bean，从而能够在方法调用时
	// 对 bean 的方法参数进行验证
	@Bean
	@ConditionalOnMissingBean
	public static MethodValidationPostProcessor methodValidationPostProcessor(Environment environment,
																			  @Lazy Validator validator) {
		MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
		boolean proxyTargetClass = environment.getProperty("spring.aop.proxy-target-class", Boolean.class, true);
		processor.setProxyTargetClass(proxyTargetClass);
		processor.setValidator(validator);
		return processor;
	}

}